package com.tanhua.admin.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.admin.mapper.AnalysisMapper;
import com.tanhua.admin.mapper.LogMapper;
import com.tanhua.commons.utils.ComputeUtil;
import com.tanhua.model.db.Analysis;
import com.tanhua.model.vo.AnalysisSummaryVo;
import com.tanhua.model.vo.AnalysisUsersVo;
import com.tanhua.model.vo.DataPointVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AnalysisService extends ServiceImpl<AnalysisMapper, Analysis> {

    @Autowired
    private LogMapper logMapper; //日志表

    @Autowired
    private AnalysisMapper analysisMapper;//日统计表

    /**
     * 计算日志表的数据，写入到日统计表中
     * 1、日统计表tb_analysis，保存或者更新
     *      根据操作的日期，查询判断
     * 2、日统计表需要的数据来源
     *      计算tb_log表中的数据
     * 3、计算tb_log编写SQL语句？
     */
    public void analysis() throws ParseException {
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String yesterday = DateUtil.yesterday().toString("yyyy-MM-dd");
        //1、准备计算的数据
        //1.1、查询注册用户数
        Integer regNum = logMapper.queryByLogTimeAndType(today, "0102");
        //1.2、登陆次数
        Integer logNum = logMapper.queryByLogTimeAndType(today, "0101");
        //1.3、活跃用户数
        Integer activeNum = logMapper.queryByLogTime(today);
        //1.4、次日留存用户数
        Integer numRetention1d = logMapper.queryNumRetention1d(today, yesterday);
        //2、根据当前日志，查询统计表
        QueryWrapper<Analysis> qw = new QueryWrapper<>();
        Date recordDate = new SimpleDateFormat("yyyy-MM-dd").parse(today); //年月日
        qw.eq("record_date",recordDate);
        Analysis analysis = analysisMapper.selectOne(qw);
        //2.1 如果数据不存在，保存统计数据
        if(analysis == null) {
            analysis = new Analysis();
            analysis.setRecordDate(recordDate);
            analysis.setNumRegistered(regNum);
            analysis.setNumActive(activeNum);
            analysis.setNumLogin(logNum);
            analysis.setNumRetention1d(numRetention1d);
            analysisMapper.insert(analysis);
        }else {
            //2.2 数据存在，更新统计数据
            analysis.setNumRegistered(regNum);
            analysis.setNumActive(activeNum);
            analysis.setNumLogin(logNum);
            analysis.setNumRetention1d(numRetention1d);
            analysisMapper.updateById(analysis);
        }
    }


    /**
     * 封装九个参数 概要统计
     * @return
     */
    public AnalysisSummaryVo summary() {

        //查询昨天和今天的记录
        String today = DateUtil.offsetDay(new Date(), 0).toDateStr();
        String yesterday = DateUtil.offsetDay(new Date(), -1).toDateStr();

        //今日数据
        QueryWrapper todayWrapper= new  QueryWrapper();
        todayWrapper.eq("record_date" , today);
        Analysis todayData = analysisMapper.selectOne(todayWrapper);

        //昨日数据
        QueryWrapper yesterdayWrapper= new  QueryWrapper();
        yesterdayWrapper.eq("record_date" , yesterday);
        Analysis yesterdayData = analysisMapper.selectOne(yesterdayWrapper);


        Long cumulativeUsers = analysisMapper.findCumulativeUsers();//累计用户数


        String monthDay = DateUtil.offsetDay(new Date(), -30).toDateStr();
        String weekDay = DateUtil.offsetDay(new Date(), -7).toDateStr();
        Long activePassMonth = analysisMapper.findActivePassByTime(monthDay , today);//过去三十天活跃用户数
        Long activePassWeek = analysisMapper.findActivePassByTime(weekDay,today);//过去七天活跃用户数
        //封装对象
        AnalysisSummaryVo vo = new AnalysisSummaryVo();

        try {
            vo.setCumulativeUsers(cumulativeUsers);//累计用户数
            vo.setActivePassMonth(activePassMonth);//过去三十天活跃用户数
            vo.setActivePassWeek(activePassWeek);//过去七天活跃用户数
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            vo.setNewUsersToday(todayData.getNumRegistered().longValue());//今日新增用户数量
            BigDecimal bigDecimal = ComputeUtil.computeRate(todayData.getNumRegistered(), yesterdayData.getNumRegistered());
            vo.setNewUsersTodayRate(bigDecimal);//今日新增用户涨跌率
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            vo.setLoginTimesToday(todayData.getNumLogin().longValue());//今日登录次数
            BigDecimal bigDecimal2 = ComputeUtil.computeRate(todayData.getNumLogin(), yesterdayData.getNumLogin());
            vo.setLoginTimesTodayRate(bigDecimal2);//今日登录次数涨跌率
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            vo.setActiveUsersToday(todayData.getNumActive().longValue());//今日活跃用户数量
            BigDecimal bigDecimal3 = ComputeUtil.computeRate(todayData.getNumActive(), yesterdayData.getNumActive());
            vo.setActiveUsersTodayRate(bigDecimal3);//今日活跃用户涨跌率
        } catch (Exception e) {
            e.printStackTrace();
        }

        return vo;
    }


    /**
     * 新增、活跃用户、次日留存率
     */
    public AnalysisUsersVo queryAnalysisUsersVo(Long sd, Long ed, Integer type) {

        DateTime startDate = DateUtil.date(sd);

        DateTime endDate = DateUtil.date(ed);

        AnalysisUsersVo analysisUsersVo = new AnalysisUsersVo();

        //今年数据
        analysisUsersVo.setThisYear(this.queryDataPointVos(startDate, endDate, type));
        //去年数据
        analysisUsersVo.setLastYear(this.queryDataPointVos(
                DateUtil.offset(startDate, DateField.YEAR, -1),
                DateUtil.offset(endDate, DateField.YEAR, -1), type)
        );

        return analysisUsersVo;
    }
    private List<DataPointVo> queryDataPointVos(DateTime sd, DateTime ed, Integer type) {

        String startDate = sd.toDateStr();

        String endDate = ed.toDateStr();

        String column = null;
        switch (type) { //101 新增 102 活跃用户 103 次日留存率
            case 101:
                column = "num_registered";
                break;
            case 102:
                column = "num_active";
                break;
            case 103:
                column = "num_retention1d";
                break;
            default:
                column = "num_active";
                break;
        }

        List<Analysis> analysisByDayList = super.list(Wrappers.<Analysis>query()
                .select("record_date , " + column + " as num_active")
                .ge("record_date", startDate)
                .le("record_date", endDate));

        return analysisByDayList.stream()
                .map(analysisByDay -> new DataPointVo(DateUtil.date(analysisByDay.getRecordDate()).toDateStr(), analysisByDay.getNumActive().longValue()))
                .collect(Collectors.toList());
    }

}
